package com.joymart.order.service;

import com.joymart.common.abstraction.FlowService;
import com.joymart.common.error.handling.JoymartBusinessException;
import com.joymart.common.model.Range;
import com.joymart.common.utils.DatetimeUtils;
import com.joymart.common.utils.SecurityUtils;
import com.joymart.compute.service.OrderGainService;
import com.joymart.compute.service.SalesPvService;
import com.joymart.compute.service.VitalityPointService;
import com.joymart.dictionary.Dictionary;
import com.joymart.dictionary.DictionaryService;
import com.joymart.order.model.Order;
import com.joymart.order.model.OrderEvent;
import com.joymart.product.service.StockService;
import com.joymart.wechat.service.WechatOpenPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.jdbc.core.JdbcAggregateTemplate;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

import static com.joymart.common.utils.CollectionUtils.asList;
import static org.springframework.data.relational.core.query.Criteria.where;

@Service
@Transactional
public class OrderFlowService extends FlowService<Order> {


    @Autowired
    private OrderService orderService;
    @Autowired
    private DictionaryService dictionaryService;
    @Autowired
    private StockService stockService;
    @Autowired
    private OrderGainService orderGainService;
    @Autowired
    private SalesPvService salesPvService;
    @Autowired
    private VitalityPointService vitalityPointService;
    @Autowired
    private OrderEventService orderEventService;
    @Autowired
    private JdbcAggregateTemplate jdbcAggregateTemplate;
    @Autowired
    private WechatOpenPlatformService wechatOpenPlatformService;
    @Value("${wechat.makeDeliveryTemplateId}")
    private String makeDeliveryTemplateId;


    /**
     * 顾客下单
     * @param order
     * @return
     */
    public String makeOrder(Order order){

        checkPerson(order, o -> !getCurrentUser().getUser().isPartyA());

        orderService.completeNewOrder(order);
        stockService.deductStock(order.getProductId(), order.getQuantity());
        orderService.modifyStatus(order, Order.Status.CREATED);
        orderService.save(order);
        orderEventService.logOrderEvent("CREATED", order);
        /**
         * 如果经营店铺自己购买，直接跳过一级店铺确认;
         */
        if(order.getBuyerId().equals(order.getFirstSellerId())){
            this.confirmBuyerPaid(order);
        }

        return order.getId();
    }


    /**
     * 买家 提醒 经营店铺 确认收款
     * @param order
     */
    public void informFirstSeller (Order order){
        checkPerson(order, o -> getCurrentUser().getId().equals(order.getBuyerId()));
        order.setFirstSellerInformed(true);
        orderService.save(order);
        orderEventService.logOrderEvent("FIRST_SELLER_INFORMED", order);
    }

    /**
     * 买家 提醒 经营店铺 确认收款
     * @param order
     */
    public void informSecondSeller(Order order){
        checkPerson(order, o -> getCurrentUser().getId().equals(order.getFirstSellerId()));
        order.setSecondSellerInformed(true);
        orderService.save(order);
        orderEventService.logOrderEvent("SECOND_SELLER_INFORMED", order);
    }

    /**
     * 经营店铺确认买家付款
     * @param order
     */
   public void confirmBuyerPaid(Order order){
        checkPerson(order, o -> getCurrentUser().getId().equals(order.getFirstSellerId()));
        orderService.checkStatus(order, Order.Status.CREATED);
        orderService.modifyStatus(order, Order.Status.BUYER_PAID);
        orderService.save(order);
        orderEventService.logOrderEvent("BUYER_PAID", order);
       /**
        * 如果管理店铺就是经营店铺（初始金店铺），直接跳过二级店铺确认;
        */
       if(order.getFirstSellerId().equals(order.getSecondSellerId())){
            this.confirmFirstSellerPaid(order);
       }
   }

    /**
     * 管理店铺确认经营店铺付款
     * @param order
     */
   public void confirmFirstSellerPaid(Order order){

       checkPerson(order, o -> getCurrentUser().getId().equals(order.getSecondSellerId()));
       orderService.checkStatus(order, Order.Status.BUYER_PAID);
       orderService.modifyStatus(order, Order.Status.FIRST_SELLER_PAID);
       orderService.save(order);
       orderEventService.logOrderEvent("FIRST_SELLER_PAID", order);
   }

    /**
     * 总部确认管理店铺付款
     * @param order
     */
   public void confirmSecondSellerPaid(Order order){
       checkPerson(order, o -> getCurrentUser().getUser().isPartyA());
       orderService.checkStatus(order, Order.Status.FIRST_SELLER_PAID);
       orderService.modifyStatus(order, Order.Status.SECOND_SELLER_PAID);
       orderService.save(order);
       // 计算活力点数
       vitalityPointService.computeOrderVitalityPoints(order);
       orderEventService.logOrderEvent("SECOND_SELLER_PAID", order);
       // 计算销售业绩
       salesPvService.computeSalesPv(order);
       // 计算收益
       orderGainService.computeOrderGain(order);

   }

    /**
     *  总部发货
     * @param order
     */
   public void makeDelivery(Order order){
       checkPerson(order, o -> getCurrentUser().getUser().isPartyA());
       orderService.checkStatus(order, Order.Status.SECOND_SELLER_PAID);
       orderService.modifyStatus(order, Order.Status.DELIVERING);
       orderService.save(order);
       orderEventService.logOrderEvent("MADE_DELIVERY", order);

       String deliveryVendorName = dictionaryService.findByName("deliveryVendors").getKeyValues().entrySet()
               .stream()
               .filter(e->e.getKey().equals(order.getDeliveryVendorId()))
               .map(Map.Entry::getValue)
               .map(Dictionary.Value::getText)
               .findFirst().orElse("其他快递");

       Map<String, Object> subMessageData =
               Map.of("character_string1", order.getId(),
                    "time2", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").format(DatetimeUtils.now()),
                    "thing3", deliveryVendorName,
                    "character_string4", order.getDeliveryNo());
       String page = "pages-orders/OrderDetails/OrderDetails?orderId=" + order.getId();
       wechatOpenPlatformService.sendSubscribeMessage(order.getBuyerId(),makeDeliveryTemplateId,subMessageData, page);
   }

    /**
     * 买家收货
     * @param order
     */
   public void receive(Order order){
       checkPerson(order, o -> getCurrentUser().getId().equals(order.getBuyerId()));
       orderService.checkStatus(order, Order.Status.DELIVERING);
       orderService.modifyStatus(order, Order.Status.RECEIVED);
       orderService.save(order);
       orderEventService.logOrderEvent("RECEIVED", order);

   }

    /**
     * 主动取消
     * @param order
     */
   public void manualCancel(Order order){
       checkCancelable(order);
       orderService.modifyStatus(order, Order.Status.CANCELLED);
       orderService.save(order);
       orderEventService.logOrderEvent("CANCELED", order);
   }


    /**
     * 自动取消，定时任务调用
     * @param order
     */
   public void autoCancel(Order order){
       orderService.modifyStatus(order, Order.Status.CANCELLED);
       orderService.save(order);
       orderEventService.logOrderEvent("CANCELED", order);
   }


    /**
     * 判断订单是否可以取消，例如当前用户是买家，状态是刚刚创建 则可以取消
     * 又或者 当前用户是买家兼经营店铺（自购） 那么即使是买家已付款的状态也可以取消
     * 具体参阅代码实现
     * @param order
     */
   private void checkCancelable(Order order){
       String currentUserId = SecurityUtils.getCurrentUserId();
       if(currentUserId.equals(order.getBuyerId()) && order.getStatus() == Order.Status.CREATED){
           return; // ok
       }else if(
               currentUserId.equals(order.getBuyerId())
                       && currentUserId.equals(order.getFirstSellerId())
                       && List.of(Order.Status.CREATED, Order.Status.BUYER_PAID).contains(order.getStatus())

       ){
           return; //ok
       }else if(
               currentUserId.equals(order.getBuyerId())
               && currentUserId.equals(order.getFirstSellerId())
               && currentUserId.equals(order.getSecondSellerId())
               && List.of(Order.Status.CREATED, Order.Status.BUYER_PAID, Order.Status.FIRST_SELLER_PAID).contains(order.getStatus())
       ){
           return ; //ok
       }else{
           throw new JoymartBusinessException("当前订单订单状态不允许取消");
       }


   }

    /**
     * 查找区间内买家未付款的订单
     *
     * @param range
     * @return
     */
    public List<Order> findTimeoutOrders(Range range) {
        Criteria criteria = where("createdAt")
                .between(range.getStart(),range.getEnd())
                .and(where("status").is(Order.Status.CREATED));
        Query query = Query.query(criteria);
        return asList(jdbcAggregateTemplate.findAll(query,Order.class));
    }

    public List<Order> findReceivingTimeoutOrders(Range range) {
        List<OrderEvent> madeDeliveryEvent = orderEventService.search("MADE_DELIVERY", range);
        List<Order> receivingTimeoutOrders = madeDeliveryEvent.stream()
                .map(orderEvent -> orderEvent.getOrderId())
                .map(orderService::getById)
                .filter(order -> order.getStatus() == Order.Status.DELIVERING)
                .toList();
        return receivingTimeoutOrders;
    }

    /**
     * 基本上和收货逻辑一样，只是通过定时任务触发，因此当前操作人是null
     * @param order
     */
    public void autoReceive(Order order) {
        orderService.modifyStatus(order, Order.Status.RECEIVED);
        orderService.save(order);
        orderEventService.logOrderEvent("RECEIVED", order);
    }
}
